﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Text;

namespace GqqCodeFirstWithSqlserver.Unicorn
{
    public class Princess : IPerson
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<Unicorn> Unicorns { get; set; }
        public virtual ICollection<LadyInWaiting> LadiesInWaiting { get; set; }
    }

    public class Unicorn
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [Timestamp]
        public byte[] Version { get; set; }

        public int PrincessId { get; set; } // FK for Princess reference
        public virtual Princess Princess { get; set; }
    }

    public class Castle
    {
        [Key]
        public string Name { get; set; }

        public Location Location { get; set; }

        public virtual ICollection<LadyInWaiting> LadiesInWaiting { get; set; }
    }

    [ComplexType]
    public class Location
    {
        public string City { get; set; }
        public string Kingdom { get; set; }

        public ImaginaryWorld ImaginaryWorld { get; set; }
    }

    [ComplexType]
    public class ImaginaryWorld
    {
        public string Name { get; set; }
        public string Creator { get; set; }
    }

    public class LadyInWaiting : IPerson
    {
        [Key, Column(Order = 0)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int PrincessId { get; set; } // FK for Princess reference

        [Key, Column(Order = 1)]
        public string CastleName { get; set; } // FK for Castle reference

        public string FirstName { get; set; }
        public string Title { get; set; }

        [NotMapped]
        public string Name
        {
            get
            {
                return String.Format("{0} {1}", Title, FirstName);
            }
        }

        public virtual Castle Castle { get; set; }
        public virtual Princess Princess { get; set; }
    }

    public interface IPerson
    {
        string Name { get; }
    }

    public class UnicornsContext : DbContext
    {
        public DbSet<Unicorn> Unicorns { get; set; }
        public DbSet<Princess> Princesses { get; set; }
        public DbSet<LadyInWaiting> LadiesInWaiting { get; set; }
        public DbSet<Castle> Castles { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            //base.OnModelCreating(modelBuilder);
        }
    }

    public class UnicornsContextInitializer : DropCreateDatabaseAlways<UnicornsContext>
    {
        protected override void Seed(UnicornsContext context)
        {
            var cinderella = new Princess { Name = "Cinderella" };
            var sleepingBeauty = new Princess { Name = "Sleeping Beauty" };
            var snowWhite = new Princess { Name = "Snow White" };

            new List<Unicorn>
            {
                new Unicorn { Name = "Binky" , Princess = cinderella },
                new Unicorn { Name = "Silly" , Princess = cinderella },
                new Unicorn { Name = "Beepy" , Princess = sleepingBeauty },
                new Unicorn { Name = "Creepy" , Princess = snowWhite }
            }.ForEach(u => context.Unicorns.Add(u));

            var efCastle = new Castle
            {
                Name = "The EF Castle",
                Location = new Location
                {
                    City = "Redmond",
                    Kingdom = "Rainier",
                    ImaginaryWorld = new ImaginaryWorld
                    {
                        Name = "Magic Unicorn World",
                        Creator = "ADO.NET"
                    }
                },
            };

            new List<LadyInWaiting>
            {
                new LadyInWaiting { Princess = cinderella,
                                    Castle = efCastle,
                                    FirstName = "Lettice",
                                    Title = "Countess" },
                new LadyInWaiting { Princess = sleepingBeauty,
                                    Castle = efCastle,
                                    FirstName = "Ulrika",
                                    Title = "Lady" },
                new LadyInWaiting { Princess = snowWhite,
                                    Castle = efCastle,
                                    FirstName = "Yolande",
                                    Title = "Duchess" }
            }.ForEach(l => context.LadiesInWaiting.Add(l));
        }
    }
}
